#ifndef _UNIFY_SYS_LOG_H_
#define _UNIFY_SYS_LOG_H_

#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/syscall.h>
#include <iostream>
#include <cstring>

using namespace std;

namespace sys {

#define _gettid() syscall(__NR_gettid)

#define LOG_CLASSNME(className) static const char* s_log_classname = #className

typedef enum {
	SOCKET_DEBUG	 = 0,
	DEBUG 		 = 1,
	INFO    		 = 2,
	WARN		 = 3,
	ERROR		 = 4
} LOG_LEVEL;

#define LOG_BUF_SIZE			2048
#define	MAX_FILENAME_LEN		256

#define LOG_INFO_NOLOCK(format, ...) \
	sys::Logger::getInstance()->writeLogNoLock(INFO, _gettid(), "#%s::%s %d, "format"\n", \
	s_log_classname, __FUNCTION__, __LINE__, ##__VA_ARGS__)

#define SOCKET_DEBUG(format, ...) \
	sys::Logger::getInstance()->writeLog(SOCKET_DEBUG, _gettid(), "#%s::%s %d, "format"\n", \
	s_log_classname, __FUNCTION__, __LINE__, ##__VA_ARGS__)

#define LOG_DEBUG(format, ...) \
	sys::Logger::getInstance()->writeLog(DEBUG, _gettid(), "#%s::%s %d, "format"\n", \
	s_log_classname, __FUNCTION__, __LINE__, ##__VA_ARGS__)

#define LOG_INFO(format, ...) \
	sys::Logger::getInstance()->writeLog(INFO, _gettid(), "#%s::%s %d, "format"\n", \
	s_log_classname, __FUNCTION__, __LINE__, ##__VA_ARGS__)

#define LOG_WARN(format, ...) \
	sys::Logger::getInstance()->writeLog(WARN, _gettid(), "#%s::%s %d, "format"\n", \
	s_log_classname, __FUNCTION__, __LINE__, ##__VA_ARGS__)	

#define LOG_ERROR(format, ...) \
	sys::Logger::getInstance()->writeLog(ERROR, _gettid(), "#%s::%s %d, "format"\n", \
	s_log_classname, __FUNCTION__, __LINE__, ##__VA_ARGS__)

class Logger 
{
public:
	Logger();
	~Logger();

	static Logger* getInstance();
	bool initLogger(const char* fileName, LOG_LEVEL minLevel);
	void writeLog(LOG_LEVEL level, int tid, const char* format, ...);
	void writeLogNoLock(LOG_LEVEL level, int tid, const char* format, ...);

private:
	void set_log(LOG_LEVEL level, int tid, const char* format, va_list);

private:
	static Logger* 		_instance;
	int 					_min_level;
	char* 				_log_file;
	char* 				_log_buf;
	FILE*				_log_fp;
	pthread_mutex_t*		_mutex;
};



}

#endif